#include <stdint.h>
#include "BaseObj.h"
#include "air780e_common.h"
#include "dataStrs.h"

#include "luat_gpio.h"
#include "common_api.h"
#include "driver_gpio.h"
#define LOG __platform_printf
// #define LOG

static luat_gpio_cfg_t* _gpio_cfg_cache[HAL_GPIO_QTY] = {0};

int pika_hal_platform_GPIO_open(pika_dev* dev, char* name) {
    // LOG("Open: %s \r\n", name);
    int pin_id = air780e_pin_name_to_id(name);
    if (pin_id < 0) {
        LOG("[ERROR] get GPIO Pin failed.\r\n");
        return -1;
    }
    if (_gpio_cfg_cache[pin_id] == NULL){
        luat_gpio_cfg_t* _gpio_cfg = pikaMalloc(sizeof(luat_gpio_cfg_t));
        _gpio_cfg_cache[pin_id] = _gpio_cfg;
        if (_gpio_cfg == NULL){
            return -1;
        }
        luat_gpio_set_default_cfg(_gpio_cfg);
        _gpio_cfg->pin = pin_id;
        dev->platform_data = _gpio_cfg;
        LOG("GPIO open new\n");
    }
    else{
        dev->platform_data = _gpio_cfg_cache[pin_id];
        LOG("GPIO reload old\n");
    }
    
    return 0;
}


int pika_hal_platform_GPIO_close(pika_dev* dev) {
    luat_gpio_cfg_t* _gpio_cfg = dev->platform_data;
    luat_gpio_close(_gpio_cfg->pin);
    _gpio_cfg_cache[_gpio_cfg->pin] = NULL;
    if (NULL != dev->platform_data) {
        pikaFree(dev->platform_data, sizeof(luat_gpio_cfg_t));
        dev->platform_data = NULL;
    }
    return 0;
}


int pika_hal_platform_GPIO_read(pika_dev* dev, void* buf, size_t count) {
    luat_gpio_cfg_t* _gpio_cfg = dev->platform_data;
    uint32_t level = luat_gpio_get(_gpio_cfg->pin);
    memcpy(buf, &level, count);
    return 0;
}

int pika_hal_platform_GPIO_write(pika_dev* dev, void* buf, size_t count) {
    luat_gpio_cfg_t* _gpio_cfg = dev->platform_data;
    uint32_t level = 0;
    memcpy(&level, buf, count);
    luat_gpio_set(_gpio_cfg->pin, level);
    return 0;
}




static int _gpio_irq_cb(int pin, void* args){
    // LOG("interrupt pin:%d\n", pin);  //中断里面用__platform_printf会崩溃
    pika_dev* dev = (pika_dev*)args;
    // luat_gpio_cfg_t* _gpio_cfg = (luat_gpio_cfg_t*)dev->platform_data;
    pika_hal_GPIO_config* cfg = (pika_hal_GPIO_config*)dev->ioctl_config;
    cfg->event_callback(dev, cfg->event_callback_filter);

}


int pika_hal_platform_GPIO_ioctl_config(pika_dev* dev, pika_hal_GPIO_config* cfg) {
    
    luat_gpio_cfg_t* _gpio_cfg = dev->platform_data;
    switch (cfg->dir) {
        case PIKA_HAL_GPIO_DIR_IN:
            _gpio_cfg->mode = LUAT_GPIO_INPUT;
            break;
        case PIKA_HAL_GPIO_DIR_OUT:
            _gpio_cfg->mode = LUAT_GPIO_OUTPUT;
            break;
        case PIKA_HAL_GPIO_IRQ:
            _gpio_cfg->mode = LUAT_GPIO_IRQ;
            break;
        default:
            _gpio_cfg->mode = LUAT_GPIO_OUTPUT;
    }
    switch (cfg->pull) {
        case PIKA_HAL_GPIO_PULL_UP:
            _gpio_cfg->pull = LUAT_GPIO_PULLUP;
            break;
        case PIKA_HAL_GPIO_PULL_DOWN:
            _gpio_cfg->pull = LUAT_GPIO_PULLDOWN;
            break;
        case PIKA_HAL_GPIO_PULL_NONE:
            _gpio_cfg->pull = LUAT_GPIO_DEFAULT;
            break;
        default:
            _gpio_cfg->pull = LUAT_GPIO_DEFAULT;
    }
    
    if (cfg->user_data != NULL){
        int altfunc = *(int *)cfg->user_data;
        GPIO_IomuxEC618(GPIO_ToPadEC618(_gpio_cfg->pin, 0), altfunc, 0, 0);
    }
    

    /* support event callback */
    if (NULL != cfg->event_callback &&
        PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE == cfg->event_callback_ena) {
        // LOG("------------ set irq\n");
        switch (cfg->event_callback_filter) {
            case PIKA_HAL_GPIO_EVENT_SIGNAL_RISING:
                _gpio_cfg->irq_type = LUAT_GPIO_RISING_IRQ;
                _gpio_cfg->irq_cb = _gpio_irq_cb;	
                _gpio_cfg->irq_args = dev;
                break;
            case PIKA_HAL_GPIO_EVENT_SIGNAL_FALLING:
                _gpio_cfg->irq_type = LUAT_GPIO_FALLING_IRQ;
                _gpio_cfg->irq_cb = _gpio_irq_cb;
                _gpio_cfg->irq_args = dev;
                break;
            case PIKA_HAL_GPIO_EVENT_SIGNAL_ANY:
                _gpio_cfg->irq_type = LUAT_GPIO_BOTH_IRQ;
                _gpio_cfg->irq_cb = _gpio_irq_cb;
                _gpio_cfg->irq_args = dev;

                break;
            default:
                LOG(
                    "[ERROR] not supported event callback filter %d\r\n",
                    cfg->event_callback_filter);
                return -1;
        }
    }
    else if (PIKA_HAL_EVENT_CALLBACK_ENA_DISABLE == cfg->event_callback_ena){
        _gpio_cfg->irq_type = 0;
        _gpio_cfg->irq_cb = NULL;
        _gpio_cfg->irq_args = NULL;
    }
    
    if (luat_gpio_open(_gpio_cfg) < 0){
        LOG("[ERROR] GPIO_ioctl_config failed.\r\n");
        return -1;
    }
    return 0;
}


int pika_hal_platform_GPIO_ioctl_enable(pika_dev* dev) {
    #if 0
    luat_gpio_cfg_t* _gpio_cfg = dev->platform_data;
    if (luat_gpio_open(_gpio_cfg) < 0){
        LOG("[ERROR] GPIO_ioctl_enable failed.\r\n");
        return -1;
    }
    #endif
    return 0;
}

int pika_hal_platform_GPIO_ioctl_disable(pika_dev* dev) {
    #if 0
    luat_gpio_cfg_t* _gpio_cfg = dev->platform_data;
    luat_gpio_close(_gpio_cfg->pin);
    #endif
    return 0;
}
